﻿using Microsoft.Practices.Prism.Commands;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Input;
using System.Xml;
using System.Xml.Serialization;

namespace HobSoft.SoccerBet2014.Client.ViewModels
{
    using Domain.ClientService;
    using Common;
    [Serializable]
    [XmlRoot("market")]
    public class BfMarket : ViewModelBase
    {
        #region command & command imple
        public ICommand FilterCommand { get; protected set; }
        public ICommand ShowAllRunnerCommand { get; protected set; }

        protected void Filter()
        {
            IsFilter = true;
        }

        public void ShowAllRunner()
        {
            blockViewRefresh = true;
            Task.Factory.StartNew(() =>
            {
                foreach (var item in Runners)
                {
                    if (item.IsFilter)
                        item.IsFilter = false;
                }

                BetApplication.Current.Dispatcher.Invoke(() =>
                {
                    System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
                    watch.Start();
                    if (!RunnersView.SortDescriptions.Any(s => s.PropertyName == "OrderIndex"))
                        RunnersView.SortDescriptions.Add(new SortDescription("OrderIndex", ListSortDirection.Ascending));
                    RunnersView.Refresh();
                    watch.Stop();
                    System.Diagnostics.Debug.WriteLine(MarketName + watch.ElapsedMilliseconds.ToString());
                });
                blockViewRefresh = false;
            });

        }
        #endregion

        private bool _hasFocus;
        [XmlIgnore]
        public bool HasFocus
        {
            get { return _hasFocus; }
            set { PropertyValueChange(ref _hasFocus, value, "HasFocus"); }
        }

        private Runner _focusRunner;
        [XmlIgnore]
        public Runner FocusRunner
        {
            get { return _focusRunner; }
            set { PropertyValueChange(ref _focusRunner, value, "FocusRunner"); }
        }
        

        private bool _isFilter = false;
        [XmlIgnore]
        public bool IsFilter
        {
            get { return _isFilter; }
            set
            {
                if (_isFilter != value && IsFilter)
                    BlurRunner();
                PropertyValueChange(ref _isFilter, value, "IsFilter");
            }
        }

        private bool blockViewRefresh = false;
        [XmlIgnore]
        public bool BlockViewRefresh
        {
            get
            {
                return blockViewRefresh;
            }
            set
            {
                blockViewRefresh = value;
            }
        }

        private ICollectionView _runnersView;
        [XmlIgnore]
        public ICollectionView RunnersView
        {
            get { return _runnersView; }
            set { PropertyValueChange(ref _runnersView, value, "RunnersView"); }
        }

        private BfEvent _event;
        [XmlIgnore]
        public BfEvent Event
        {
            get { return _event; }
            set { PropertyValueChange(ref _event, value, "Event");  }
        }

        private IBfRequestService _bfRequestService;
        [XmlIgnore]
        public IBfRequestService BfRequestService
        {
            get
            {
                if (_bfRequestService == null && Event != null)
                    _bfRequestService = Event.BFRequestService;
                return _bfRequestService;
            }
            set
            {
                _bfRequestService = value;
            }
        }
        public BfMarket()
        {
            FilterCommand = new DelegateCommand(Filter);
            ShowAllRunnerCommand = new DelegateCommand(ShowAllRunner);
        }

        #region property model
        private int _eventID;
        [XmlIgnore]
        public int EventID
        {
            get { return _eventID; }
            set { PropertyValueChange(ref _eventID, value, "EventID"); }
        }

        private string _marketID;
        [XmlAttribute("market-id")]
        public string MarketID
        {
            get { return _marketID; }
            set { PropertyValueChange(ref _marketID, value, "MarketID"); }
        }

        private byte _marketCategory;
        [XmlAttribute("category")]
        public byte MarketCategory
        {
            get { return _marketCategory; }
            set { PropertyValueChange(ref _marketCategory, value, "MarketCategory"); }
        }

        private string _marketName;
        [XmlAttribute("market-name")]
        public string MarketName
        {
            get { return _marketName; }
            set { PropertyValueChange(ref _marketName, value, "MarketName"); }
        }

        private string _marketStatus;
        [XmlAttribute("market-status")]
        public string MarketStatus
        {
            get { return _marketStatus; }
            set { PropertyValueChange(ref _marketStatus, value, "MarketStatus"); }
        }

        private decimal _amount;
        [XmlAttribute("amount")]
        public decimal Amount
        {
            get { return _amount; }
            set { PropertyValueChange(ref _amount, value, "Amount"); }
        }

        private ObservableCollection<Runner> _runners;
        [XmlElement("runner")]
        public ObservableCollection<Runner> Runners
        {
            get { return _runners; }
            set
            {
                PropertyValueChange(ref _runners, value, "Runners");
                if (_runners != null)
                {
                    foreach (Runner item in _runners)
                    {
                        item.PropertyChanged += Runner_PropertyChanged;
                        item.Market = this;
                    }
                    _runners.CollectionChanged += Runners_CollectionChanged;
                }
                if (value != null)
                    InitializeView();
                else
                    RunnersView = null;
            }
        }
        #endregion

        private void Runners_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if(e.Action== System.Collections.Specialized.NotifyCollectionChangedAction.Add
                || e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace)
            {
                foreach (Runner item in e.NewItems)
                {
                    item.PropertyChanged += Runner_PropertyChanged;
                    item.Market = this;
                }
            }
        }

        private void Runner_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsFilter")
            {
                if (!blockViewRefresh)
                {
                    System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
                    watch.Start();
                    RunnersView.Refresh();
                    watch.Stop();
                    System.Diagnostics.Debug.WriteLine(watch.ElapsedMilliseconds);
                }
            }
            else if (e.PropertyName == "IsFocus")
            {
                var rn = sender as Runner;
                HasFocus = Runners.Any(r => r.IsFocus);
                if (rn == null || !rn.IsFocus)
                {
                    FocusRunner = null;
                    return;
                }
                FocusRunner = rn;
                foreach (var item in Runners)
                {
                    if (item != sender && item.IsFocus)
                        item.IsFocus = false;
                }
            }
        }

        public void BlurRunner()
        {
            HasFocus = false;
            FocusRunner = null;
            foreach (var item in Runners)
            {
                if (item.IsFocus)
                    item.IsFocus = false;
            }
        }

        protected void InitializeView()
        {
            RunnersView = new ListCollectionView(Runners);
            RunnersView.SortDescriptions.Add(new SortDescription("OrderIndex", ListSortDirection.Ascending));
            RunnersView.Filter = (r) => ((Runner)r).IsFilter == false;
        }
    }
}
